/****************************************************************************
 * Copyright (c) 2008, 2009 Andreas Unger and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andreas Unger - initial API and implementation 
 ****************************************************************************/

package org.esmp.sysml.componentmodel.codegen;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.UMLPlugin;
import org.eclipse.xtend.typesystem.emf.EcoreUtil2;
import org.eclipse.xtend.typesystem.emf.Mapping;
import org.eclipse.xtend.typesystem.uml2.Setup;

import com.cea.papyrus.uml4sysml.sysml.SysmlPackage;
import com.cea.papyrus.uml4sysml.sysml.activities.ActivitiesPackage;
import com.cea.papyrus.uml4sysml.sysml.allocations.AllocationsPackage;
import com.cea.papyrus.uml4sysml.sysml.blocks.BlocksPackage;
import com.cea.papyrus.uml4sysml.sysml.constraints.ConstraintsPackage;
import com.cea.papyrus.uml4sysml.sysml.interactions.InteractionsPackage;
import com.cea.papyrus.uml4sysml.sysml.modelelements.ModelelementsPackage;
import com.cea.papyrus.uml4sysml.sysml.portandflows.PortandflowsPackage;
import com.cea.papyrus.uml4sysml.sysml.requirements.RequirementsPackage;
import com.cea.papyrus.uml4sysml.sysml.statemachines.StatemachinesPackage;
import com.cea.papyrus.uml4sysml.sysml.usecases.UsecasesPackage;

/**
 * @author Andreas Unger
 *
 */
public class SysMLSetup extends Setup {

	private static final String CLASSPATH_ERROR_MESSAGE = "Missing required plugin '%s' in classpath.";
	private static final String SYSML_PLUGIN_NAME = "com.cea.papyrus.uml4sysml.extension";
	
	/**
	 * 
	 */
	public SysMLSetup() {
		addEPackageClass(SysmlPackage.eINSTANCE.getClass().getName());
		addEPackageClass(ModelelementsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(BlocksPackage.eINSTANCE.getClass().getName());
		addEPackageClass(PortandflowsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(ConstraintsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(ActivitiesPackage.eINSTANCE.getClass().getName());
		addEPackageClass(AllocationsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(RequirementsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(InteractionsPackage.eINSTANCE.getClass().getName());
		addEPackageClass(StatemachinesPackage.eINSTANCE.getClass().getName());
		addEPackageClass(UsecasesPackage.eINSTANCE.getClass().getName());
	}
	
	public void setSysMLSetup(boolean b) {
		super.setStandardUML2Setup(b);
		if (b) {
			registerSysMLProfile();
			EPackage.Registry.INSTANCE.put("http://www.eclipse.org/uml2/2.1.0/UML", EPackage.Registry.INSTANCE.get(UMLPackage.eINSTANCE.getNsURI()));
		}
	}
	
	private void registerSysMLProfile() {
		String p = "model/SysML.profile.uml";
		URI uri = EcoreUtil2.getURI(p);
		if (uri != null && !uri.toString().equals(p)) {
			String path = uri.toString();
			final int mmIndex = path.lastIndexOf("/model");
			if (mmIndex < 0) {
				throw new IllegalStateException(createClasspathErrorMessage(SYSML_PLUGIN_NAME));
			}
			path = path.substring(0, mmIndex);
			path = addJarProtocolIfNecessary(path);
			addUriMap(new Mapping("pathmap://SysML_PROFILES/", path + "/model/"));
			addUriMap(new Mapping("pathmap://SysML_LIBRARIES/", path + "/libraries/"));
			addUriMap(new Mapping("platform:/plugin/com.cea.papyrus.uml4sysml.extension/model/", path + "/model/"));
			
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/1", URI.createURI(path + "/model/SysML.profile.uml#_TZ_nULU5EduiKqCzJMWbGw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/ModelElements/1", URI.createURI(path + "/model/SysML.profile.uml#_Gx8MgLX7EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Blocks/1", URI.createURI(path + "/model/SysML.profile.uml#_fSw28LX7EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/PortAndFlows/1", URI.createURI(path + "/model/SysML.profile.uml#_rpx28LX7EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Constraints/1", URI.createURI(path + "/model/SysML.profile.uml#_5WYJ0LX7EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Activities/1", URI.createURI(path + "/model/SysML.profile.uml#_C2zXMLX8EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Allocations/1", URI.createURI(path + "/model/SysML.profile.uml#_NxdG4LX8EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Requirements/1", URI.createURI(path + "/model/SysML.profile.uml#_OOJC4LX8EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/Interactions/1", URI.createURI(path + "/model/SysML.profile.uml#_meOioLX8EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/StateMachines/1", URI.createURI(path + "/model/SysML.profile.uml#_nAF5kLX8EduFmqQsrNB9lw"));
			UMLPlugin.getEPackageNsURIToProfileLocationMap().put("http://www.papyrusuml.org/SysML/UseCases/1", URI.createURI(path + "/model/SysML.profile.uml#_neZmMLX8EduFmqQsrNB9lw"));
		} else {
			throw new IllegalStateException(createClasspathErrorMessage(SYSML_PLUGIN_NAME));
		}
	}

	/**
	 * Fixes a resource path of a Jar file, if necessary.
	 * 
	 * @param path
	 *            A resource path
	 * @return If the path ends with '.jar', but has no protocol prefix 'jar:',
	 *         the prefix is prepended. Otherwise path is returned unchanged.
	 */
	protected String addJarProtocolIfNecessary(String path) {
		if (path.indexOf(".jar!") != -1) {
			if (!path.startsWith("jar:"))
				path = "jar:" + path;
		}
		return path;
	}
	
	protected String createClasspathErrorMessage(String pluginName) {
		return String.format(CLASSPATH_ERROR_MESSAGE, pluginName);
	}

}
